package avicit.bdp.dms.tdm.service;

import avicit.bdp.common.base.BaseService;
import avicit.bdp.common.utils.BdpLogUtil;
import avicit.bdp.core.constant.Constants;
import avicit.bdp.core.util.json.JSONUtils;
import avicit.bdp.dms.tdm.dao.AssetPortalDao;
import avicit.bdp.dms.tdm.dao.BdpAssetDao;
import avicit.bdp.dms.tdm.dto.AssetApplyDTO;
import avicit.bdp.dms.tdm.dto.AssetTagDTO;
import avicit.bdp.dms.tdm.dto.BdpAssetCatalogDTO;
import avicit.bdp.dms.tdm.dto.BdpAssetDTO;
import avicit.bdp.dms.tdm.dto.BdpAssetMountDataServiceDTO;
import avicit.bdp.dms.tdm.dto.BdpAssetMountFileDTO;
import avicit.bdp.dms.tdm.dto.BdpAssetMountModelDTO;
import avicit.bdp.dms.tdm.dto.BdpAssetMountReportDTO;
import avicit.bdp.dms.tdm.dto.ProcessApproveDTO;
import avicit.bdp.dms.tdm.utils.CheckerStatus;
import avicit.bdp.dms.tdm.utils.FlowType;
import avicit.bdp.dms.tdm.utils.ReleaseStatus;
import avicit.platform6.api.syslookup.dto.SysLookupSimpleVo;
import avicit.platform6.api.system.ConvertColumnClient;
import avicit.platform6.api.system.SysLookupClient;
import avicit.platform6.api.system.SysOrgClient;
import avicit.platform6.api.system.impl.SystemConstant;
import avicit.platform6.api.sysuser.dto.SysOrg;
import avicit.platform6.commons.utils.BusinessUtil;
import avicit.platform6.commons.utils.ComUtil;
import avicit.platform6.commons.utils.ObjectUtil;
import avicit.platform6.commons.utils.PojoUtil;
import avicit.platform6.core.context.ThreadContextHelper;
import avicit.platform6.core.exception.BusinessException;
import avicit.platform6.core.properties.PlatformConstant;
import avicit.platform6.core.rest.msg.QueryRespBean;
import avicit.platform6.modules.system.syslog.service.SysLogUtil;
import com.alibaba.fastjson2.JSONArray;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@Service
@Transactional
public class BdpAssetService extends BaseService<BdpAssetDao, BdpAssetDTO> {

    @Resource
    private BdpAssetMountModelService bdpAssetMountModelService;
    @Resource
    private BdpAssetMountFileService bdpAssetMountFileService;
    @Resource
    private BdpAssetMountDataServiceService bdpAssetMountDataServiceService;
    @Resource
    private BdpAssetMountReportService bdpAssetMountReportService;
    @Autowired
    private ConvertColumnClient convertColumnClient;
    @Autowired
    private SysOrgClient sysOrgClient;
    @Autowired
    private ProcessApproveService processApproveService;
    @Autowired
    private AssetApplyService assetApplyService;
    @Autowired
    private AssetTagService assetTagService;
    @Autowired
    private AssetPortalDao asssetPortalDao;
    @Autowired
    private SysLookupClient sysLookupClient;
    @Autowired
    private BdpAssetCatalogService bdpAssetCatalogService;

    public QueryRespBean<BdpAssetDTO> getPageList(
            String catalogId,
            String assetType,
            String keyWords,
            String releaseTitle,
            Integer releaseStatus,
            String releaseDateBegin,
            String releaseDateEnd,
            Integer status,
            Integer pageNo,
            Integer pageSize)
            throws Exception {

        List<String> catalogIdList = new ArrayList<>();
        if (StringUtils.isNotBlank(catalogId)) {
            catalogIdList.add(catalogId);
        }

        QueryRespBean<BdpAssetDTO> queryRespBean = new QueryRespBean<>();

        //文档密级
        List<String> wordSecretList = ThreadContextHelper.getWordSecretList();
        PageHelper.startPage(pageNo, pageSize);

        Page<BdpAssetDTO> page =
                this.mapper.getPageList(
                        assetType,
                        null,
                        catalogIdList,
                        keyWords,
                        releaseTitle,
                        releaseStatus,
                        releaseDateBegin,
                        releaseDateEnd,
                        0, ThreadContextHelper.getUserId(), wordSecretList);
        valueConvert(page.getResult());
        queryRespBean.setResult(page);
        BdpLogUtil.log4Query(queryRespBean);
        return queryRespBean;
    }

    public List<BdpAssetDTO> getList(
            String catalogId,
            String assetType,
            String keyWords,
            String releaseTitle,
            Integer releaseStatus,
            String releaseDateBegin,
            String releaseDateEnd,
            Integer status)
            throws Exception {

        List<String> catalogIdList = new ArrayList<>();
        if (StringUtils.isNotBlank(catalogId)) {
            catalogIdList.add(catalogId);
        }
        //文档密级
        List<String> wordSecretList = ThreadContextHelper.getWordSecretList();

        List<BdpAssetDTO> list =
                this.mapper.getPageList(
                        assetType,
                        null,
                        catalogIdList,
                        keyWords,
                        releaseTitle,
                        releaseStatus,
                        releaseDateBegin,
                        releaseDateEnd,
                        status, ThreadContextHelper.getUserId(), wordSecretList);

        return list;
    }

    private Map<String, String> getAllSysOrg() {
        Map<String, String> map = new HashMap<>();
        List<SysOrg> orgList = sysOrgClient.getAllSysOrgList();
        if (CollectionUtils.isNotEmpty(orgList)) {
            for (SysOrg org : orgList) {
                map.put(org.getId(), org.getOrgName());
            }
        }
        return map;
    }

    /**
     * 通过主键查询单条记录
     *
     * @param id 主键id
     */
    @Transactional(readOnly = true)
    public BdpAssetDTO queryById(String id) {
        try {
            BdpAssetDTO dto = this.selectByPrimaryKey(id);
            //发布的服务
            Map<String, String> serviceTypeMap = new HashMap<>();
            Collection<SysLookupSimpleVo> lookupList = sysLookupClient.getLookUpListByTypeByAppIdNoFilter("BDP_DAM_APPLY_SERVICE_TYPE", ThreadContextHelper.getAppId());
            for (SysLookupSimpleVo vo : lookupList) {
                serviceTypeMap.put(vo.getLookupCode(), vo.getLookupName());
            }
            //ArrayList idList = new ArrayList();
            //idList.add(dto.getId());
            //List<BdpAssetMountFileDTO> assetMountList = asssetPortalDao.getAssetMountFileList(idList);
            if (StringUtils.isNotEmpty(dto.getOpenServiceType())) {
                //BdpAssetMountFileDTO assetMount = assetMountList.get(0);
                //dto.setOpenServiceType(assetMount.getOpenServiceType());
                dto.setOpenServiceTypeName(convertType(dto.getOpenServiceType(), serviceTypeMap));
            }
            if (StringUtils.isNotBlank(dto.getCatalogId())) {
                BdpAssetCatalogDTO catalogDTO = bdpAssetCatalogService.queryById(dto.getCatalogId());
                if (catalogDTO != null) {
                    dto.setCatalogName(catalogDTO.getClassifyName());
                }
            }
            //标签
            List<AssetTagDTO> assetTagDTOList = assetTagService.findAssetTagListByAssetId(id);
            if (CollectionUtils.isNotEmpty(assetTagDTOList)) {
                String tagNames = assetTagDTOList.stream().map(p -> p.getTagName()).collect(Collectors.joining(","));
                dto.setLabelNames(tagNames);
                List<String> tagIdList = assetTagDTOList.stream().map(p -> p.getTagId()).collect(Collectors.toList());
                dto.setLabels(JSONUtils.toJson(tagIdList));
            }
            //发布部门
            Map<String, Set<String>> convertFormData = new HashMap<>();
            List<String> idLists = new ArrayList<>();
            BusinessUtil.createConvertSet(convertFormData, SystemConstant.DEPT, dto.getReleaseDept());
            idLists.add(dto.getId());
            // 获取请求结果
            Map<String, Map<String, String>> convertResultData = convertColumnClient.replace(convertFormData);
            // 发布部门
            dto.setReleaseDeptName(
                    BusinessUtil.convertFormat(convertResultData, SystemConstant.DEPT, dto.getReleaseDept()));
            // 记录日志
            if (dto != null) {
                SysLogUtil.log4Query(dto);
                valueConvert(Collections.singletonList(dto));
            }

            BdpLogUtil.log4Query(dto);
            return dto;
        } catch (Exception e) {
            throw new BusinessException(e.getMessage(), e);
        }
    }

    /**
     * 转换申请服务代码名称
     */
    private String convertType(String code, Map<String, String> serviceTypeMap) {
        if (StringUtils.isBlank(code)) {
            return "";
        }
        String[] codes = code.split(",");
        List<String> list = new ArrayList<>();
        for (String c : codes) {
            list.add(serviceTypeMap.getOrDefault(c, ""));
        }
        return String.join(",", list);
    }

    /**
     * 新增对象
     *
     * @param dto 保存对象
     * @return String
     */
    @Transactional
    public String save(BdpAssetDTO dto) {
        try {
            dto.setId(ComUtil.getId());
            // 验证资产标题 TODO 暂时不校验
//            BdpAssetDTO query = new BdpAssetDTO();
//            query.setReleaseTitle(dto.getReleaseTitle());
//            query.setCreatedBy(ThreadContextHelper.getUserId());
//            Long count = this.selectCount(query);
//            if (count > 0) {
//                throw new BusinessException("发布标题已存在");
//            }
            //处理标签字段
            handleAssetLables(dto);

            // 默认未发布  0： 未发布、  1 ： 已发布
            dto.setReleaseStatus(ReleaseStatus.WAIT_PUBLISH.getCode());
            dto.setCheckerStatus(CheckerStatus.WAIT_PUBLISH.getCode());
            //查询次数
            dto.setViewCount(0L);
            dto.setStatus(0);
            //请求次数
            dto.setCallCount(0L);

            this.insert(dto);
            // 记录日志
            SysLogUtil.log4Insert(dto);
            return dto.getId();
        } catch (Exception e) {
            throw new BusinessException(e.getMessage(), e);
        }
    }

    /**
     * 处理资产修改时，更新标签关联表
     *
     * @param dto
     * @return void
     * @date 2024/3/27 15:43
     */
    public void handleAssetLables(BdpAssetDTO dto) {
        AssetTagDTO delTagQuery = new AssetTagDTO();
        delTagQuery.setAssetId(dto.getId());
        assetTagService.delete(delTagQuery);
        if (StringUtils.isBlank(dto.getLabels())) {
            return;
        }
        List<String> tagIdList = JSONUtils.toList(dto.getLabels(), String.class);
        if (CollectionUtils.isNotEmpty(tagIdList)) {
            for (String id : tagIdList) {
                AssetTagDTO assetTagDTO = new AssetTagDTO();
                assetTagDTO.setId(ComUtil.getId());
                assetTagDTO.setAssetId(dto.getId());
                assetTagDTO.setTagId(id.trim());
                assetTagService.insert(assetTagDTO);
            }
        }
        dto.setLabels(null);
    }

    /**
     * 修改对象部分字段
     *
     * @param dto 修改对象
     * @return int
     */
    @Transactional
    public int update(BdpAssetDTO dto) {
        try {
            //处理标签字段
            handleAssetLables(dto);

            BdpAssetDTO oldDTO = getUpdateDto(dto);
            int count = this.updateByPrimaryKey(oldDTO);
            BdpLogUtil.log4Update(dto, oldDTO);

            if (count == 0) {
                throw new BusinessException("数据失效，请重新更新");
            }
            return count;
        } catch (Exception e) {
            throw new BusinessException(e.getMessage(), e);
        }
    }

    /**
     * 内部方法，获取修改的dto对象
     */
    private BdpAssetDTO getUpdateDto(BdpAssetDTO dto) {
        BdpAssetDTO oldDTO = selectByPrimaryKey(dto.getId());
        if (oldDTO == null) {
            throw new BusinessException("数据不存在");
        }
        //不更新开放服务类型
        dto.setOpenServiceType(oldDTO.getOpenServiceType());
        // 记录日志
        SysLogUtil.log4Update(dto, oldDTO);

        PojoUtil.copyProperties(oldDTO, dto, true);
        if (StringUtils.isNotBlank(dto.getSecretLevel())) {
            oldDTO.setSecretLevel(dto.getSecretLevel());
        }
        logger.debug("资产更新密级:" + oldDTO.getSecretLevel());
        return oldDTO;
    }

    public Boolean deleteById(String id) {
        //部分已经有申请记录的资产，不允许实际被删除
        AssetApplyDTO query = new AssetApplyDTO();
        query.setAssetId(id);
        List<AssetApplyDTO> list = assetApplyService.selectListWithoutOrgId(query);
        ProcessApproveDTO processQuery = new ProcessApproveDTO();
        processQuery.setBusinessId(id);
        List<ProcessApproveDTO> processList = processApproveService.selectListWithoutOrgId(processQuery);
        if (CollectionUtils.isEmpty(list) && CollectionUtils.isEmpty(processList)) {
            BdpAssetMountModelDTO deleteMountModelDto = new BdpAssetMountModelDTO();
            deleteMountModelDto.setAssetId(id);
            bdpAssetMountModelService.delete(deleteMountModelDto);

            BdpAssetMountFileDTO deleteMountFileDto = new BdpAssetMountFileDTO();
            deleteMountFileDto.setAssetId(id);
            bdpAssetMountFileService.delete(deleteMountFileDto);

            BdpAssetMountDataServiceDTO deleteDataServiceDto = new BdpAssetMountDataServiceDTO();
            deleteDataServiceDto.setAssetId(id);
            bdpAssetMountDataServiceService.delete(deleteDataServiceDto);

            BdpAssetMountReportDTO deleteMountReportDTO = new BdpAssetMountReportDTO();
            deleteMountReportDTO.setAssetId(id);
            bdpAssetMountReportService.delete(deleteMountReportDTO);
            this.deleteByPrimaryKey(id);
        } else {
            BdpAssetDTO oldDTO = selectByPrimaryKey(id);
            if (oldDTO == null) {
                throw new BusinessException("数据不存在");
            }
            oldDTO.setStatus(1);
            this.updateByPrimaryKey(oldDTO);
        }

        String logTitle = "删除数据资产：【" + id + "】";
        BdpLogUtil.log("数据资产模块", logTitle, PlatformConstant.OpType.delete);

        return true;
    }

    /**
     * 通过平台API将字段值转换为名称，包括通用选择组件、通用代码
     *
     * @param list list
     */
    private void valueConvert(List<BdpAssetDTO> list) {
        if (CollectionUtils.isNotEmpty(list)) {
            // 循环组装请求数据
            Map<String, Set<String>> convertFormData = new HashMap<>();
            List<String> idLists = new ArrayList<>();
            for (BdpAssetDTO dto : list) {
                BusinessUtil.createConvertSet(
                        convertFormData, Constants.BDP_DATA_SECRET_LEVEL_KEY, dto.getSecretLevel());
                BusinessUtil.createConvertSet(convertFormData, SystemConstant.USER, dto.getReleaser());
                BusinessUtil.createConvertSet(convertFormData, SystemConstant.USER, dto.getCreatedBy());
                BusinessUtil.createConvertSet(convertFormData, SystemConstant.DEPT, dto.getReleaseDept());
                BusinessUtil.createConvertSet(convertFormData, "BDP_DAM_RESOURCE_TYPE", dto.getAssetType());
                BusinessUtil.createConvertSet(convertFormData, "BDP_DAM_ASSET_SOURCE", dto.getSourceSystem());
                idLists.add(dto.getId());
            }
            // 获取申请信息列表
            List<ProcessApproveDTO> processList = processApproveService.queryProcessApproveByBusinessIdList(idLists);
            Map<String, ProcessApproveDTO> processMap = processList.stream().collect(Collectors.toMap(ProcessApproveDTO::getBusinessId, ProcessApproveDTO -> ProcessApproveDTO));
            Map<String, String> orgMap = getAllSysOrg();
            // 获取请求结果
            Map<String, Map<String, String>> convertResultData = convertColumnClient.replace(convertFormData);
            // 循环设置Alias或Name的值
            for (BdpAssetDTO dto : list) {
                dto.setSecretLevelName(
                        BusinessUtil.convertFormat(
                                convertResultData, Constants.BDP_DATA_SECRET_LEVEL_KEY, dto.getSecretLevel()));
                // 发布人
                dto.setReleaserName(
                        BusinessUtil.convertFormat(convertResultData, SystemConstant.USER, dto.getReleaser()));
                dto.setReleaseDeptName(BusinessUtil.convertFormat(convertResultData, SystemConstant.DEPT, dto.getReleaseDept()));
                // 创建人
                dto.setCreatedName(
                        BusinessUtil.convertFormat(convertResultData, SystemConstant.USER, dto.getCreatedBy()));
                //资产类型
                dto.setAssetTypeName(BusinessUtil.convertFormat(convertResultData, "BDP_DAM_RESOURCE_TYPE", dto.getAssetType()));
                //数据来源
                dto.setSourceSystemName(BusinessUtil.convertFormat(
                        convertResultData, "BDP_DAM_ASSET_SOURCE", dto.getSourceSystem()));
                // 业务方法
                this.handleValueConvert(dto, orgMap);

                dto.setCheckerStatusName(CheckerStatus.getDescByCode(dto.getCheckerStatus()));

                ProcessApproveDTO processDto = processMap.get(dto.getId());
                if (processDto != null) {
                    dto.setProcessId(processDto.getId());
                    dto.setDbid_(processDto.getDbid_());
                    dto.setActivityalias_(processDto.getActivityalias_());
                    dto.setActivityname_(BusinessUtil.processStateCode2StateName(processDto.getActivityalias_()));
                    dto.setBusinessstate_(processDto.getBusinessstate_());
                }

            }
        }
    }

    /**
     * 目录数据以及范围转化
     *
     * @param dto 数据对象
     */
    private void handleValueConvert(BdpAssetDTO dto, Map<String, String> orgMap) {

        if (StringUtils.isNotBlank(dto.getReleaseScope())) {
            JSONArray array = JSONUtils.parseArray(dto.getReleaseScope());
            List<String> idList = array.toJavaList(String.class);
            List<String> scopeNames = new ArrayList<>();
            for (String orgId : idList) {
                String orgName = orgMap.get(orgId);
                if (ObjectUtil.isNotEmpty(orgName)) {
                    scopeNames.add(orgName);
                }
            }

            if (CollectionUtils.isNotEmpty(scopeNames)) {
                dto.setReleaseScopeShowName(String.join(",", scopeNames));
            }
        }
    }

    public void addViewCount(BdpAssetDTO asset) {
        BdpAssetDTO dto = new BdpAssetDTO();
        if (StringUtils.isBlank(asset.getId())) {
            throw new BusinessException("id为空！");
        }
        BdpAssetDTO old = this.selectByPrimaryKey(asset.getId());
        Long oldCount = old.getViewCount();
        dto.setId(old.getId());
        dto.setViewCount(oldCount + 1);
        this.updateByPrimaryKeySelective(dto);
    }

    /**
     * 撤回资产发布的申请
     *
     * @param id
     * @return boolean
     * @date 2024/3/27 10:02
     */
    public boolean revokeAssetById(String id) {
        if (StringUtils.isBlank(id)) {
            throw new BusinessException("id为空！");
        }
        BdpAssetDTO bdpAssetDTO = this.selectByPrimaryKey(id);
        if (bdpAssetDTO == null) {
            throw new BusinessException("资产不存在！");
        }
        bdpAssetDTO.setCheckerStatus(CheckerStatus.WAIT_REVOKE_APPROVE.getCode());
        this.updateByPrimaryKey(bdpAssetDTO);
        ProcessApproveDTO processApproveDTO = new ProcessApproveDTO();
        processApproveDTO.setFlowType(FlowType.REVOKE.getCode());
        processApproveDTO.setBusinessId(id);
        processApproveDTO.setBusinessTitle(bdpAssetDTO.getReleaseTitle() + " - 撤回的申请");
        //启动当前用户所在组织流程
        String result = processApproveService.startProcessTask(processApproveDTO, "bdp_asset_publish", ThreadContextHelper.getOrgId());

        String logTitle = "撤回id为：【" + id + "】的数据资产申请";
        BdpLogUtil.log("数据资产模块", logTitle, PlatformConstant.OpType.update);
        return true;
    }

    /**
     * 资产发布的申请
     *
     * @param id
     * @return boolean
     * @date 2024/3/27 10:03
     */
    public boolean publishAssetById(String id) {
        if (StringUtils.isBlank(id)) {
            throw new BusinessException("id为空！");
        }
        BdpAssetDTO bdpAssetDTO = this.selectByPrimaryKey(id);
        if (bdpAssetDTO == null) {
            throw new BusinessException("资产不存在！");
        }
        bdpAssetDTO.setCheckerStatus(CheckerStatus.WAIT_PUBLISH_APPROVE.getCode());
        this.updateByPrimaryKey(bdpAssetDTO);
        ProcessApproveDTO processApproveDTO = new ProcessApproveDTO();
        processApproveDTO.setFlowType(FlowType.PUBLISH.getCode());
        processApproveDTO.setBusinessId(id);
        processApproveDTO.setBusinessTitle(bdpAssetDTO.getReleaseTitle() + " - 发布的申请");
        //启动当前用户所在组织流程
        String result = processApproveService.startProcessTask(processApproveDTO, "bdp_asset_publish", ThreadContextHelper.getOrgId());

        String logTitle = "申请id为：【" + id + "】的数据资产";
        BdpLogUtil.log("数据资产模块", logTitle, PlatformConstant.OpType.update);
        return true;
    }

    public void addCallCount(String assetId){
        this.mapper.addCallCount(assetId);
    }
}
